package com.jinke.api.modules.third.sjgj2.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.util.CommonUtil;
import com.jinke.api.common.util.Global;
import com.jinke.api.modules.app.enums.BalanceLogType;
import com.jinke.api.modules.app.enums.OrderStatus;
import com.jinke.api.modules.app.enums.OrderType;
import com.jinke.api.modules.app.enums.ValidateStatus;
import com.jinke.api.modules.app.model.Order;
import com.jinke.api.modules.app.model.OrderParcel;
import com.jinke.api.modules.app.response.CreateLabel2Response;
import com.jinke.api.modules.app.service.IUserOrderTaskService;
import com.jinke.api.modules.app.service.OrderParcelService;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.app.service.UserRechargeService;
import com.jinke.api.modules.app.util.MathUtil;
import com.jinke.api.modules.app.util.OssUtil;
import com.jinke.api.modules.base.service.ThirdService;
import com.jinke.api.modules.third.ezeeship.model.request.EstimateRateRequest;
import com.jinke.api.modules.third.ezeeship.model.response.CreateLabelResponse;
import com.jinke.api.modules.third.ezeeship.model.response.EstimateRateResponse;
import com.jinke.api.modules.third.ezeeship.util.EzeeShipUtil;
import com.jinke.api.modules.third.sjgj.model.response.CreateOrderResponse;
import com.jinke.api.modules.third.sjgj.model.response.GetPriceResponse;
import com.jinke.api.modules.third.sjgj2.service.Sjgj2Service;
import com.jinke.api.modules.third.sjgj2.util.Sjgjwl2Util;
import com.jinke.api.modules.ums.model.Channel;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.service.ChannelService;
import com.jinke.api.modules.ums.service.UmsAdminService;
import com.jinke.api.modules.ums.vo.UserChannelVO;
import com.jinke.api.security.util.ApiUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author macro
 * @since 2024-01-13
 */
@Service
@Slf4j
public class Sjgj2ServiceImpl implements Sjgj2Service {
    @Resource
    private UmsAdminService umsAdminService;
    @Resource
    private ChannelService channelService;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private Sjgjwl2Util sjgjwl2Util;
    @Resource
    private OrderService orderService;
    @Resource
    private IUserOrderTaskService iUserOrderTaskService;

    @Resource
    private OrderParcelService orderParcelService;

    @Resource
    private UserRechargeService userRechargeService;
    @Resource
    private ThirdService thirdService;
    @Resource
    private EzeeShipUtil ezeeShipUtil;

    @Override
    public CommonResult estimateRate(EstimateRateRequest request) {
        Integer userId = ApiUserUtil.getUserId();
        return estimateRate(request, userId);
    }

    @Override
    public CommonResult estimateRate(EstimateRateRequest request, Integer userId) {
        UserChannelVO userChannelVO = request.getUserChannelVO();
        Channel channel = userChannelVO.getChannel();
        request.setServiceCode(channel.getChannelCode());
        BigDecimal rateAmount;
        try {
            rateAmount = getPrice(request, userId, userChannelVO, channel.getChannelCode());
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        if (rateAmount.compareTo(new BigDecimal("0")) <= 0) {
            return CommonResult.failed("系统异常，请联系管理人员");
        }
        EstimateRateResponse.Data newData = new EstimateRateResponse.Data();
        newData.setRate(rateAmount);
        return CommonResult.success(newData);
    }

    private BigDecimal getPrice(EstimateRateRequest request, Integer userId, UserChannelVO userChannelVO, String code) {
        BigDecimal rateAmount = new BigDecimal("0");
        String strResult = sjgjwl2Util.getPrice(request, code);
        if (StringUtils.isNotEmpty(strResult)) {
            GetPriceResponse getPriceResponse = JSONUtil.toBean(strResult, GetPriceResponse.class);
            GetPriceResponse.GetPriceResponseDetail getPriceResponseDetail = getPriceResponse.getResult().get(0);
            if (!getPriceResponse.isSuccess()) {
                throw new RuntimeException(getPriceResponseDetail.getMsg());
            }
            rateAmount = getPriceResponseDetail.getPost_fee()
                    .add(getPriceResponseDetail.getCl_fee())
                    .add(getPriceResponseDetail.getOther_fee())
                    .add(getPriceResponseDetail.getRanyou_fee())
                    .add(getPriceResponseDetail.getGh_fee());
            rateAmount = thirdService.calcRate(userId, userChannelVO, rateAmount);
        }
        return rateAmount;
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request) {
        Integer userId =ApiUserUtil.getUserId();
        return createLabel(request, userId);
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request, Integer userId) {
        request.setOrderNO(StringUtils.isEmpty(request.getOrderNO()) ? CommonUtil.getOrderNo() : request.getOrderNO());
        Channel channel = channelService.getOne(new LambdaQueryWrapper<Channel>().eq(Channel::getId, request.getChannelId()));
        BigDecimal rateAmount;
        try {
            rateAmount = getPrice(request, userId, request.getUserChannelVO(), channel.getChannelCode());
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        UmsAdmin umsAdmin = umsAdminService.getById(userId);
        if (ObjectUtils.isEmpty(umsAdmin) || rateAmount.compareTo(new BigDecimal("0")) <= 0) {
            return CommonResult.failed("系统异常,请联系管理人员");
        }
        BigDecimal totalAmount = umsAdmin.getCreditBalance().add(umsAdmin.getBalance());
        if (totalAmount.compareTo(rateAmount) < 0) {
            return CommonResult.failed("Insufficient Balance");
        }
        String strResult = sjgjwl2Util.createOrder(request, channel.getChannelCode());
        if (StringUtils.isNotEmpty(strResult)) {
            CreateOrderResponse createOrderResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            Order order = new Order();
            BeanUtils.copyProperties(request, order);
            order.setId(request.getOrderId());
            if (ObjectUtils.isNotEmpty(umsAdmin.getSellerId())){
                order.setSellerId(umsAdmin.getSellerId());
            }
            if (createOrderResponse.toCommonResult().isSucess()) {
                //设置错误信息为空
                order.setErrMsg("");
                order.setUserId(userId);
                order.setOrderNo(request.getOrderNO());
                CreateOrderResponse.CreateOrderResponseDetail createOrderResponseDetail = createOrderResponse.getResult().get(0);
                CreateOrderResponse.GetPriceResponseDetail price = createOrderResponseDetail.getPrice();
                BigDecimal afterRate = price.getPost_fee()
                        .add(price.getCl_fee())
                        .add(price.getOther_fee())
                        .add(price.getRanyou_fee())
                        .add(price.getGh_fee()
                        );
                order.setOriginFee(afterRate);

                afterRate = thirdService.calcRate(userId, request.getUserChannelVO(), afterRate);
                order.setRate(afterRate);

                // 上传到oss
                String objectId = createOrderResponseDetail.getOrderid();


                // 扣钱
                BigDecimal finalRate = afterRate;
                if (finalRate != null && BigDecimal.ZERO.compareTo(finalRate) < 0) {
                    userRechargeService.decrTransfer(userId, finalRate, BalanceLogType.CONSUME, "寄件", order.getOrderNo(),objectId,channel,null);
                }

                String pdfUrl = createOrderResponseDetail.getLabel_url();
                ossUtil.upload("pdf", objectId + ".pdf", pdfUrl);

                String newPdfUrl = Global.PRINT_LABEL_API + objectId;


                // order.setCreateTime(LocalDateTime.now());

                try {
                    order.setReference(request.getExtra().getReference());
                    order.setReference2(request.getExtra().getReference2());
                }catch (Exception e){
                    log.error("设置reference出错了");
                }

                order.setFromCity(request.getFrom().getCity());
                order.setFromEmail(request.getFrom().getEmail());
                order.setFromCompany(request.getFrom().getCompany());
                order.setFromPhone(request.getFrom().getPhone());
                order.setFromAddressLine2(request.getFrom().getAddressLine2());
                order.setFromAddressLine1(request.getFrom().getAddressLine1());
                order.setFromCountryCode(request.getFrom().getCountryCode());
                order.setFromZipCode(request.getFrom().getZipCode());
                order.setFromPersonName(request.getFrom().getPersonName());
                order.setFromStateCode(request.getFrom().getStateCode());

                EstimateRateRequest.Address requestTo = request.getTo();
                order.setToCity(requestTo.getCity());
                order.setToEmail(requestTo.getEmail());
                order.setToCompany(requestTo.getCompany());
                order.setToPhone(requestTo.getPhone());
                order.setToAddressLine2(requestTo.getAddressLine2());
                order.setToAddressLine1(requestTo.getAddressLine1());
                order.setToCountryCode(requestTo.getCountryCode());
                order.setToZipCode(requestTo.getZipCode());
                order.setToPersonName(requestTo.getPersonName());
                order.setToStateCode(requestTo.getStateCode());
                order.setOrderType(OrderType.API);

                order.setPdfUrl(newPdfUrl);
                order.setStatus(OrderStatus.RECENT.getValue());
                order.setObjectId(objectId);

                order.setCreateTime(LocalDateTime.now());
                if (BooleanUtil.isTrue(requestTo.getIsValid())) {
                    order.setValidateStatus(ValidateStatus.defaultEnum(requestTo.getIsResidential()));
                } else {
                    order.setValidateStatus(ValidateStatus.UN_VALIDATE);
                }

                BigDecimal earnestRate = umsAdmin.getEarnestRate();
                BigDecimal subEarnestBalance = MathUtil.formatBigDecimal(afterRate.multiply(earnestRate));
                order.setEarnest(subEarnestBalance);

                orderService.saveOrUpdate(order);

                iUserOrderTaskService.saveByOrderId(order.getId());

                Integer orderId = order.getId();
                List<EstimateRateRequest.Parcel> parcels = request.getParcels();
                String trackingno = createOrderResponseDetail.getTrackingno();
                String label_url  = createOrderResponseDetail.getLabel_url();
                //更新包裹
                updateParcel(userId,  orderId, parcels,trackingno,label_url);

                //组装返回
                CreateLabelResponse.Data newCreateLabelResponseData = getCreateLabelReturn(createOrderResponseDetail, objectId, finalRate, newPdfUrl);

                return CommonResult.success(newCreateLabelResponseData);
            } else {
                String message = createOrderResponse.toCommonResult().getMessage().replaceAll("接口返回：：", "");
                message = ezeeShipUtil.fmtMsg(message);
                if (order.getId() != null) {
                    orderService.update(new LambdaUpdateWrapper<Order>().eq(Order::getId, order.getId()).set(Order::getErrMsg, message));
                }
                return CommonResult.failed(message);
            }
        }
        return CommonResult.success();
    }

    /**
     * 组装返回
     * @param createOrderResponseDetail
     * @param objectId
     * @param finalRate
     * @param newPdfUrl
     * @return
     */
    @NotNull
    private CreateLabelResponse.Data getCreateLabelReturn(CreateOrderResponse.CreateOrderResponseDetail createOrderResponseDetail, String objectId, BigDecimal finalRate, String newPdfUrl) {
        CreateLabelResponse.Data newCreateLabelResponseData = new CreateLabelResponse.Data();
        newCreateLabelResponseData.setRate(finalRate);

        CreateLabel2Response.FeeDetail newFeeDetail = new CreateLabel2Response.FeeDetail();
        newFeeDetail.setBaseRate(finalRate);
        newCreateLabelResponseData.setFeeDetail(newFeeDetail);

        newCreateLabelResponseData.setRate(finalRate);
        newCreateLabelResponseData.setStatus(1);
        newCreateLabelResponseData.setCreateTime(LocalDateTime.now());
        newCreateLabelResponseData.setObjectId(objectId);
        newCreateLabelResponseData.setPdfUrl(newPdfUrl);
        newCreateLabelResponseData.setTrackingNumber(Arrays.asList(createOrderResponseDetail.getTrackingno()));
        String labelUrl = Global.PRINT_LABEL_API + objectId;
        newCreateLabelResponseData.setLabelUrl(Arrays.asList(labelUrl));
        return newCreateLabelResponseData;
    }

    /**
     * 更新包裹
     * @param userId
     * @param
     * @param orderId
     * @param parcels
     */
    @Transactional
    void updateParcel(Integer userId, Integer orderId, List<EstimateRateRequest.Parcel> parcels, String trackingn, String label_url) {
        List<OrderParcel> orderParcels = parcels.stream().map(x -> {
            OrderParcel orderParcel = new OrderParcel();
            orderParcel.setOrderId(orderId);
            orderParcel.setUserId(userId);
            BeanUtils.copyProperties(x, orderParcel);
            EstimateRateRequest.Extra extra = x.getExtra();
            if (extra != null) {
                BeanUtils.copyProperties(extra, orderParcel);
            }
            // 设置追踪号和标签 URL
            orderParcel.setTrackingNumber(trackingn);
            orderParcel.setLabelUrl(label_url);

            return orderParcel;
        }).collect(Collectors.toList());


        orderParcelService.remove(new LambdaQueryWrapper<OrderParcel>().eq(OrderParcel::getOrderId, orderId));
        // 入库
        orderParcelService.saveBatch(orderParcels);
    }

    @Override
    public CommonResult getLabel(String objectId) {

        return getLabel(objectId, null);

    }

    @Override
    public CommonResult getLabel(String objectId, Integer userId) {
        log.info(JSONUtil.toJsonStr(objectId));

        CreateLabelResponse.Data createLabelResponseData = new CreateLabelResponse.Data();

        if (userId == null) {
            userId = ApiUserUtil.getUserId();
        }
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getObjectId, objectId)
                .eq(Order::getUserId, userId)
        );

        if (order == null) {
            return CommonResult.success(createLabelResponseData);
        }

        CreateLabelResponse.Data newCreateLabelResponseData = new CreateLabelResponse.Data();
        newCreateLabelResponseData.setObjectId(objectId);
        newCreateLabelResponseData.setPdfUrl(order.getPdfUrl());
        BigDecimal finalRate = order.getRate();
        newCreateLabelResponseData.setRate(finalRate);
        newCreateLabelResponseData.setStatus(createLabelResponseData.getStatus());
        CreateLabel2Response.FeeDetail newFeeDetail = new CreateLabel2Response.FeeDetail();
        newFeeDetail.setBaseRate(finalRate);
        newCreateLabelResponseData.setFeeDetail(newFeeDetail);

        newCreateLabelResponseData.setCreateTime(createLabelResponseData.getCreateTime());
        newCreateLabelResponseData.setTrackingNumber(createLabelResponseData.getTrackingNumber());

        String labelUrl = Global.PRINT_LABEL_API + objectId;
        newCreateLabelResponseData.setLabelUrl(Arrays.asList(labelUrl));
        return CommonResult.success(newCreateLabelResponseData);

    }

    @Override
    public CommonResult cancelLabel(String objectId,String orderNo) {
        String strResult = sjgjwl2Util.cancelLabel(objectId,orderNo);
        if (StringUtils.isNotBlank(strResult)) {
            CreateOrderResponse createLabelResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            List<CreateOrderResponse.CreateOrderResponseDetail> result = createLabelResponse.getResult();
            if (CollectionUtil.isNotEmpty(result)) {
                if (result.get(0).getCode() != 300) {
                    return CommonResult.failed(result.get(0).getMsg());
                }
            }
        }
        return CommonResult.success();
    }

    @Override
    public CommonResult tracking(String trackingNumber) {
        String strResult = sjgjwl2Util.tracking(trackingNumber);
        if (StringUtils.isNotBlank(strResult)) {
            CreateOrderResponse createLabelResponse = JSONUtil.toBean(strResult, CreateOrderResponse.class);
            List<CreateOrderResponse.CreateOrderResponseDetail> result = createLabelResponse.getResult();
            if (CollectionUtil.isNotEmpty(result)) {
                if (result.get(0).getCode() != 300) {
                    return CommonResult.failed(result.get(0).getMsg());
                }
            }

        }
        return CommonResult.success();
    }

    @Override
    public CommonResult cancelInsurance(String insuranceId) {

        return CommonResult.success();
    }
}
